home *** CD-ROM | disk | FTP | other *** search
- #include <Memory.h>
- #include <Palettes.h>
- #include <Dialogs.h>
- #include <GestaltEqu.h>
- #include "Dim_text.h"
-
- static pascal void Dim_text_proc( short byteCnt, Ptr textAddr,
- Point numerPt, Point denomPt );
- static void Gray_frame_rect( Rect *bounds );
- static pascal void Gray_frame_draw_proc( short depth, short dev_flags,
- GDHandle dev, Rect *bounds );
-
- /* ---------------------------------------------------------------------
- Dim_text This is a group of routines for dimming text
- items in dialogs. As is, it assumes that you are
- not using the dialog's refCon for anything else,
- and that you are not using the QuickDraw
- bottlenecks for anything else.
-
- This code can be used freely. I ask that you tell me about any
- improvements that you think of.
-
- James W. Walker May 4, 1994
- JWWalker@AOL.com
- 76367.2271@compuserve.com
- ---------------------------------------------------------------------
- */
-
- #define SYSTEM_6_COMPATIBLE 1
-
- typedef struct Dim_list_el {
- short item_num;
- struct Dim_list_el *next;
- Rect bounds;
- Boolean editable;
- } Dim_list_el;
-
- typedef struct {
- Dim_list_el *dim_list;
- QDTextUPP Old_text_proc;
- #if SYSTEM_6_COMPATIBLE
- Boolean has_gray_text;
- #endif
- } Dim_data;
-
-
- /* ---------------------------------------------------------------------
- Get_dim_data Macro to get the list head.
- Just used to encapsulate the use of the refCon,
- so that if you need to store the list head
- somewhere else you will only need to change this
- and Init_dimmer.
- ---------------------------------------------------------------------
- */
- #define Get_dim_data( dp ) ((Dim_data *) ((WindowPeek)dp)->refCon)
-
-
- /* ---------------------------------------------------------------------
- Init_dimmer Set up a dialog for dimming text. Call it once, soon
- after creating the dialog.
- ---------------------------------------------------------------------
- */
- void Init_dimmer( DialogPtr dp )
- {
- Dim_data *dim_head;
- QDProcs *qd_procs;
- long val;
-
- dim_head = (Dim_data *) NewPtrClear( sizeof(Dim_data) );
- if (dim_head)
- {
- // Store the pointer where we can find it later
- ((WindowPeek)dp)->refCon = (long) dim_head;
-
- // Patch the QuickDraw bottleneck for text
- if ( (dp->portBits.rowBytes & 0x8000) == 0 ) // B&W port
- {
- qd_procs = (QDProcs *) NewPtrSysClear( sizeof(QDProcs) );
- SetStdProcs( qd_procs );
- }
- else // color port
- {
- qd_procs = (QDProcs *) NewPtrSysClear( sizeof(CQDProcs) );
- SetStdCProcs( (CQDProcs *) qd_procs );
- }
- dim_head->Old_text_proc = qd_procs->textProc;
- qd_procs->textProc = NewQDTextProc( Dim_text_proc );
- dp->grafProcs = qd_procs;
-
- #if SYSTEM_6_COMPATIBLE
- // Which System 7 features are available?
- dim_head->has_gray_text =
- (Gestalt( gestaltQuickdrawFeatures, &val ) == noErr)
- && ( (val & (1L << gestaltHasGrayishTextOr)) != 0 );
- #endif
-
- } // end if (dim_head)
- }
-
-
- /* ---------------------------------------------------------------------
- Dispose_dimmer Called once after you are through with a dialog.
- ---------------------------------------------------------------------
- */
- void Dispose_dimmer( DialogPtr dp )
- {
- Dim_data *dim_head;
- Dim_list_el *this_el, *next;
-
- dim_head = Get_dim_data(dp);
- if (dim_head)
- {
- this_el = dim_head->dim_list;
- while (this_el != NULL)
- {
- EraseRect( &this_el->bounds );
- next = this_el->next;
- DisposePtr( (Ptr) this_el );
- this_el = next;
- }
-
- DisposePtr( (Ptr) dim_head );
- }
-
- if (dp->grafProcs)
- {
- DisposeRoutineDescriptor( qd_procs->textProc );
- DisposePtr( (Ptr) dp->grafProcs );
- }
- dp->grafProcs = NULL;
- }
-
- /* ---------------------------------------------------------------------
- Dim_text Set the dimming state of a text item.
- ---------------------------------------------------------------------
- */
- void Dim_text( DialogPtr dp, short item, Boolean dim )
- {
- Dim_data *dim_head;
- Dim_list_el *dimmable, *predecessor;
- Rect iRect;
- Handle iHandle;
- short iType;
- short disable_flag;
-
- dim_head = Get_dim_data(dp);
- if (dim_head != NULL)
- {
- GetDItem( dp, item, &iType, &iHandle, &iRect );
- disable_flag = iType & itemDisable;
-
- // Try to find the right item number in the list.
- dimmable = dim_head->dim_list;
- while ( (dimmable != NULL) && (dimmable->item_num != item) )
- {
- dimmable = dimmable->next;
- }
-
- if ( (dimmable == NULL) && dim ) // dim it
- {
- dimmable = (Dim_list_el *)
- NewPtrClear( sizeof(Dim_list_el) );
- if (dimmable)
- {
- dimmable->next = dim_head->dim_list;
- dim_head->dim_list = dimmable;
- dimmable->item_num = item;
- dimmable->editable = (iType & editText) != 0;
- dimmable->bounds = iRect;
- if (dimmable->editable)
- {
- InsetRect( &dimmable->bounds, -3, -3 );
- /*
- To dim an editable text item, we need to turn it
- into a static text item, and also take some care
- that it is not showing the insertion point or a
- selection range.
- */
- TEDeactivate( ((DialogPeek) dp)->textH );
- if (item == ((DialogPeek) dp)->editField + 1 )
- {
- SelIText( dp, item, 0, 0 );
- ((DialogPeek) dp)->editField = -1;
- }
- SetDItem( dp, item, statText | disable_flag,
- iHandle, &iRect );
- ((DialogPeek) dp)->editField = -1;
- TEActivate( ((DialogPeek) dp)->textH );
- InvalRect( &dimmable->bounds );
- }
- else
- {
- InvalRect( &iRect );
- }
- }
- }
- else if ( (dimmable != NULL) && !dim ) // undim it
- {
- // Remove it from the list
- if (dim_head->dim_list == dimmable)
- {
- dim_head->dim_list = dimmable->next;
- }
- else
- {
- predecessor = dim_head->dim_list;
- while (predecessor->next != dimmable)
- {
- predecessor = predecessor->next;
- }
- predecessor->next = dimmable->next;
- }
-
- if (dimmable->editable)
- {
- SetDItem( dp, item, editText | disable_flag,
- iHandle, &iRect );
- SelIText( dp, item, 0, 0 );
- EraseRect( &iRect );
- FrameRect( &dimmable->bounds );
- TEUpdate( &iRect, ((DialogPeek) dp)->textH );
- }
- else
- {
- InvalRect( &iRect );
- }
-
- // Delete the list element
- DisposePtr( (Ptr) dimmable );
- }
- }
- }
-
-
- /* ---------------------------------------------------------------------
- Dim_text_proc The QuickDraw bottleneck routine that does
- the actual dimming, and also draws the frame
- around dimmed editable text.
- ---------------------------------------------------------------------
- */
- static pascal void Dim_text_proc( short byteCnt, Ptr textAddr,
- Point numerPt, Point denomPt )
- {
- short item_num;
- DialogPtr dp;
- Dim_list_el *dimmable;
- Dim_data *dim_head;
- Rect gray_rect;
- PenState save_pen;
-
- GetPort( &dp );
- dim_head = Get_dim_data( dp );
- item_num = FindDItem( dp, dp->pnLoc ) + 1;
- dimmable = dim_head->dim_list;
- while ( (dimmable != NULL) && (dimmable->item_num != item_num) )
- {
- dimmable = dimmable->next;
- }
- if ( dimmable != NULL )
- {
- #if SYSTEM_6_COMPATIBLE
- if (dim_head->has_gray_text)
- #endif
- {
- TextMode( grayishTextOr );
- }
- if (dimmable->editable)
- {
- Gray_frame_rect( &dimmable->bounds );
- }
- }
-
- CallQDTextProc( dim_head->Old_text_proc, byteCnt, textAddr,
- numerPt, denomPt );
-
- #if SYSTEM_6_COMPATIBLE
- if ( !dim_head->has_gray_text && (dimmable != NULL) )
- {
- gray_rect = dimmable->bounds;
- InsetRect( &gray_rect, 1, 1 );
- GetPenState( &save_pen );
- PenMode( patBic );
- /*
- The reason I used a string literal rather than the QuickDraw
- global gray is so that it can be used in a code resource
- without problems.
- */
- PenPat( (ConstPatternParam) "\xAA\x55\xAA\x55\xAA\x55\xAA\x55" );
- PaintRect( &gray_rect );
- SetPenState( &save_pen );
- }
- #endif
- }
-
- /* ---------------------------------------------------------------------
- Gray_frame_draw_proc DeviceLoop drawing procedure called
- by Gray_frame_rect.
- ---------------------------------------------------------------------
- */
- static pascal void Gray_frame_draw_proc( short depth, short dev_flags,
- GDHandle dev, Rect *bounds )
- {
- RGBColor fore_color, back_color, gray_color;
-
- if (depth > 1)
- {
- GetForeColor( &fore_color );
- GetBackColor( &back_color );
- gray_color = fore_color;
- GetGray( dev, &back_color, &gray_color );
- RGBForeColor( &gray_color );
- }
- else
- {
- PenPat( (ConstPatternParam) "\xAA\x55\xAA\x55\xAA\x55\xAA\x55" );
- }
-
- FrameRect( bounds );
-
- if (depth > 1)
- {
- RGBForeColor( &fore_color );
- }
- else
- {
- PenNormal();
- }
- }
-
- /* ---------------------------------------------------------------------
- Gray_frame_rect Draw a gray rectangle; true gray
- if possible, dithered otherwise.
- ---------------------------------------------------------------------
- */
- static void Gray_frame_rect( Rect *bounds )
- {
- RgnHandle save_clip, draw_rgn;
- DeviceLoopDrawingUPP Draw_UPP;
-
- PenNormal();
- save_clip = NewRgn();
- GetClip( save_clip );
- draw_rgn = NewRgn();
- RectRgn( draw_rgn, bounds );
- SetClip( draw_rgn );
- Draw_UPP = NewDeviceLoopDrawingProc( Gray_frame_draw_proc );
- DeviceLoop( draw_rgn, Draw_UPP, (long) bounds, 0 );
- DisposeRoutineDescriptor( Draw_UPP );
- SetClip( save_clip );
- DisposeRgn( draw_rgn );
- DisposeRgn( save_clip );
- PenNormal();
- }
-